home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / net / netamsrc.arc / slip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-02-09  |  7.5 KB  |  335 lines

  1. /* Send and receive IP datagrams on serial lines. Compatible with SLIP
  2.  * under Berkeley Unix.
  3.  */
  4. #include <stdio.h>
  5. #include "global.h"
  6. #include "mbuf.h"
  7. #include "iface.h"
  8. #include "ax25.h"
  9. #include "slip.h"
  10. #ifdef UNIX    /* BSD or SYS5 */
  11. #include "unix.h"
  12. #else
  13. #ifdef AMIGA
  14. #include "amiga.h"
  15. #else
  16. #ifdef MAC
  17. #include "mac.h"
  18. #else
  19. #include "pc.h"
  20. #include "asy.h"
  21. #endif MAC
  22. #endif AMIGA
  23. #endif        /* BSD or SYS5 */
  24. #include "trace.h"
  25.  
  26. int asy_ioctl();
  27. int kiss_ioctl();
  28. int slip_send();
  29. int doslip();
  30. int asy_output();
  31.  
  32. /* Slip level control structure */
  33. struct slip slip[ASY_MAX];
  34.  
  35. /* Send routine for point-to-point slip
  36.  * This is a trivial function since there is no slip link-level header
  37.  */
  38. int
  39. slip_send(bp,interface,gateway,precedence,delay,throughput,reliability)
  40. struct mbuf *bp;        /* Buffer to send */
  41. struct interface *interface;    /* Pointer to interface control block */
  42. int32 gateway;            /* Ignored (SLIP is point-to-point) */
  43. char precedence;
  44. char delay;
  45. char throughput;
  46. char reliability;
  47. {
  48.     if(interface == NULLIF){
  49.         free_p(bp);
  50.         return;
  51.     }
  52.     dump(interface,IF_TRACE_OUT,TRACE_IP,bp);
  53.     (*interface->raw)(interface,bp);
  54. }
  55. /* Send a raw slip frame -- also trivial */
  56. slip_raw(interface,bp)
  57. struct interface *interface;
  58. struct mbuf *bp;
  59. {
  60.     /* Queue a frame on the slip output queue and start transmitter */
  61.     slipq(interface->dev,bp);
  62. }
  63. /* Encode a raw packet in slip framing, put on link output queue, and kick
  64.  * transmitter
  65.  */
  66. static
  67. slipq(dev,bp)
  68. int16 dev;        /* Serial line number */
  69. struct mbuf *bp;    /* Buffer to be sent */
  70. {
  71.     register struct slip *sp;
  72.     struct mbuf *slip_encode();
  73.  
  74.     if((bp = slip_encode(bp)) == NULLBUF)
  75.         return;    
  76.  
  77.     sp = &slip[dev];
  78.     enqueue(&sp->sndq,bp);
  79.     sp->sndcnt++;
  80.     if(sp->tbp == NULLBUF)
  81.         asy_start(dev);
  82. }
  83. /* Start output, if possible, on asynch device dev */
  84. static
  85. asy_start(dev)
  86. int16 dev;
  87. {
  88.     register struct slip *sp;
  89.  
  90.     if(!stxrdy(dev))
  91.         return;        /* Transmitter not ready */
  92.  
  93.     sp = &slip[dev];
  94.     if(sp->tbp != NULLBUF){
  95.         /* transmission just completed */
  96.         free_p(sp->tbp);
  97.         sp->tbp = NULLBUF;
  98.     }
  99.     if(sp->sndq == NULLBUF)
  100.         return;    /* No work */
  101.  
  102.     sp->tbp = dequeue(&sp->sndq);
  103.     sp->sndcnt--;
  104.     asy_output(dev,sp->tbp->data,sp->tbp->cnt);
  105. }
  106. /* Encode a packet in SLIP format */
  107. static
  108. struct mbuf *
  109. slip_encode(bp)
  110. struct mbuf *bp;
  111. {
  112.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  113.     register char *cp;
  114.     register int cnt;
  115.     char c;
  116.  
  117.     /* Allocate output mbuf that's twice as long as the packet.
  118.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  119.      */
  120.     lbp = alloc_mbuf(2*len_mbuf(bp) + 2);
  121.     if(lbp == NULLBUF){
  122.         /* No space; drop */
  123.         free_p(bp);
  124.         return NULLBUF;
  125.     }
  126.     cp = lbp->data;
  127.     cnt = 0;
  128.  
  129.     /* Flush out any line garbage */
  130.     *cp++ = FR_END;
  131.     cnt++;
  132.  
  133.     /* Copy input to output, escaping special characters */
  134.     while(pullup(&bp,&c,1) == 1){
  135.         switch(c & 0xff){
  136.         case FR_ESC:
  137.             *cp++ = FR_ESC;
  138.             *cp++ = T_FR_ESC;
  139.             cnt += 2;
  140.             break;
  141.         case FR_END:
  142.             *cp++ = FR_ESC;
  143.             *cp++ = T_FR_END;
  144.             cnt += 2;
  145.             break;
  146.         default:
  147.             *cp++ = c;
  148.             cnt++;
  149.         }
  150.     }
  151.     *cp++ = FR_END;
  152.     cnt++;
  153.     lbp->cnt = cnt;
  154.     return lbp;
  155. }
  156. /* Process incoming bytes in SLIP format
  157.  * When a buffer is complete, return it; otherwise NULLBUF
  158.  */
  159. static
  160. struct mbuf *
  161. slip_decode(dev,c)
  162. int16 dev;    /* Slip unit number */
  163. char c;        /* Incoming character */
  164. {
  165.     struct mbuf *bp,*nbp;
  166.     register struct slip *sp;
  167.  
  168.     sp = &slip[dev];
  169.     switch(c & 0xff){
  170.     case FR_END:
  171.         bp = sp->rbp;
  172.         sp->rbp = NULLBUF;
  173.         sp->rcnt = 0;
  174.         return bp;    /* Will be NULLBUF if empty frame */
  175.     case FR_ESC:
  176.         sp->escaped = 1;
  177.         return NULLBUF;
  178.     }
  179.     if(sp->escaped){
  180.         /* Translate 2-char escape sequence back to original char */
  181.         sp->escaped = 0;
  182.         switch(c & 0xff){
  183.         case T_FR_ESC:
  184.             c = FR_ESC;
  185.             break;
  186.         case T_FR_END:
  187.             c = FR_END;
  188.             break;
  189.         default:
  190.             sp->errors++;
  191.             break;
  192.         }
  193.     }
  194.     /* We reach here with a character for the buffer;
  195.      * make sure there's space for it
  196.      */
  197.     if(sp->rbp == NULLBUF){
  198.         /* Allocate first mbuf for new packet */
  199.         if((sp->rbp1 = sp->rbp = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  200.             return NULLBUF; /* No memory, drop */
  201.         sp->rcp = sp->rbp->data;
  202.     } else if(sp->rbp1->cnt == SLIP_ALLOC){
  203.         /* Current mbuf is full; link in another */
  204.         if((sp->rbp1->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  205.             /* No memory, drop whole thing */
  206.             free_p(sp->rbp);
  207.             sp->rbp = NULLBUF;
  208.             sp->rcnt = 0;
  209.             return NULLBUF;
  210.         }
  211.         sp->rbp1 = sp->rbp1->next;
  212.         sp->rcp = sp->rbp1->data;
  213.     }
  214.     /* Store the character, increment fragment and total
  215.      * byte counts
  216.      */
  217.     *sp->rcp++ = c;
  218.     sp->rbp1->cnt++;
  219.     sp->rcnt++;
  220.     return NULLBUF;
  221. }
  222. /* Process SLIP line I/O */
  223. int
  224. doslip(interface)
  225. struct interface *interface;
  226. {
  227.     char c;
  228.     struct mbuf *bp;
  229.     int16 dev;
  230.     int16 asy_recv();
  231.  
  232.     dev = interface->dev;
  233.     /* Process any pending input */
  234.     while(asy_recv(dev,&c,1) != 0)
  235.         if((bp = slip_decode(dev,c)) != NULLBUF)
  236.             (*slip[dev].recv)(interface,bp);
  237.  
  238.     /* Kick the transmitter if it's idle */
  239.     if(stxrdy(dev))
  240.         asy_start(dev);
  241. }
  242. /* Unwrap incoming SLIP packets -- trivial operation since there's no
  243.  * link level header
  244.  */
  245. slip_recv(interface,bp)
  246. struct interface *interface;
  247. struct mbuf *bp;
  248. {
  249.     void ip_route();
  250.  
  251.     /* By definition, all incoming packets are "addressed" to us */
  252.     dump(interface,IF_TRACE_IN,TRACE_IP,bp);
  253.     ip_route(bp,0);
  254. }
  255. /* Attach a serial interface to the system
  256.  * argv[0]: hardware type, must be "asy"
  257.  * argv[1]: I/O address, e.g., "0x3f8"
  258.  * argv[2]: vector, e.g., "4"
  259.  * argv[3]: mode, may be:
  260.  *        "slip" (point-to-point SLIP)
  261.  *        "ax25" (AX.25 frame format in SLIP for raw TNC)
  262.  * argv[4]: interface label, e.g., "sl0"
  263.  * argv[5]: receiver ring buffer size in bytes
  264.  * argv[6]: maximum transmission unit, bytes
  265.  * argv[7]: interface speed, e.g, "9600"
  266.  */
  267. asy_attach(argc,argv)
  268. int argc;
  269. char *argv[];
  270. {
  271.     register struct interface *if_asy;
  272.     extern struct interface *ifaces;
  273.     int16 dev;
  274.     int asy_init();
  275.     int asy_send();
  276.     int doslip();
  277.     int asy_stop();
  278.     int ax_send();
  279.     int ax_output();
  280.     int kiss_recv();
  281.     int kiss_raw();
  282.  
  283.     if(nasy >= ASY_MAX){
  284.         printf("Too many asynch controllers\n");
  285.         return -1;
  286.     }
  287.     dev = nasy++;
  288. #if    (defined(AMIGA) || defined(MAC) || defined(UNIX) )
  289.     asy[dev].tty = malloc(strlen(argv[2])+1);
  290.     strcpy(asy[dev].tty, argv[2]);
  291. #else
  292.  
  293.     /* Initialize hardware-level control structure */
  294.     asy[dev].addr = htoi(argv[1]);
  295.     asy[dev].vec = htoi(argv[2]);
  296. #endif    /* BSD or SYS5 */
  297.     /* Create interface structure and fill in details */
  298.     if_asy = (struct interface *)calloc(1,sizeof(struct interface));
  299.  
  300.     if_asy->name = malloc((unsigned)strlen(argv[4])+1);
  301.     strcpy(if_asy->name,argv[4]);
  302.     if_asy->mtu = atoi(argv[6]);
  303.     if_asy->dev = dev;
  304.     if_asy->recv = doslip;
  305.     if_asy->stop = asy_stop;
  306.  
  307.     if(strcmp(argv[3],"slip") == 0){
  308.         if_asy->ioctl = asy_ioctl;
  309.         if_asy->send = slip_send;
  310.         if_asy->output = NULLFP;    /* ARP isn't used */
  311.         if_asy->raw = slip_raw;
  312.         if_asy->flags = 0;
  313.         slip[dev].recv = slip_recv;
  314.     }
  315.     else if(strcmp(argv[3],"ax25") == 0){
  316.         /* This function is done in main.c so it can be easily
  317.          * ifdef'ed out
  318.          */
  319.         if(kiss_attach(if_asy,&slip[dev].recv) == -1){
  320.             free((char *)if_asy);
  321.             return -1;
  322.         }
  323.     } else {
  324.         printf("Mode %s unknown for interface %s\n",
  325.             argv[3],argv[4]);
  326.         free((char *)if_asy);
  327.         return -1;
  328.     }
  329.     if_asy->next = ifaces;
  330.     ifaces = if_asy;
  331.     asy_init(dev,(unsigned)atoi(argv[5]));
  332.     asy_speed(dev,atoi(argv[7]));
  333.     return 0;
  334. }
  335.